import { useEffect, useRef, useState } from 'react'
import styles from './scss/ImageCompare.module.scss'
import { isMobile } from '@/utils/adaptation'
import { type imagePreviewModes } from '@/store/imageUpscaleConfig'
interface Props {
  originUrl: string
  upScaleUrl: string
  width: number
  height: number
  /**
   * 图片放大倍数
   */
  outImageScale: number
  /**
   * canvas缩放倍数
   */
  canvasScale?: number
  previewMode: (typeof imagePreviewModes)[number]
}

const transformToCanvasPos = (
  canvas: HTMLCanvasElement,
  event: { clientX: number; clientY: number }
) => {
  const rect = canvas.getBoundingClientRect()
  const offsetX = event.clientX - rect.left
  const offsetY = event.clientY - rect.top
  // 计算缩放比例
  const scaleX = canvas.width / canvas.clientWidth
  const scaleY = canvas.height / canvas.clientHeight
  // 转换坐标
  const x = offsetX * scaleX
  const y = offsetY * scaleY
  return { x, y }
}
/**
 * 根据最后在区域的位置判断 在哪个方向划出的
 *
 */
const calculationMouseOutDir = (
  lastPos: { x: number; y: number },
  width: number,
  height: number
) => {
  const dLeft = lastPos.x
  const dRight = width - lastPos.x
  const dTop = lastPos.y
  const dBottom = height - lastPos.y
  const min = Math.min(dLeft, dRight, dTop, dBottom)
  if (min === dLeft) {
    return 'left'
  } else if (min === dRight) {
    return 'right'
  } else if (min === dTop) {
    return 'top'
  } else if (min === dBottom) {
    return 'bottom'
  }
}
/**
 * 图片比较器
 * @returns
 */
function ImageCompare(props: Props) {
  const {
    originUrl: orgingUrl,
    upScaleUrl,
    width,
    height,
    outImageScale,
    canvasScale = 1,
  } = props
  const canvasRef = useRef<HTMLCanvasElement>(null)
  const originImage = useRef<HTMLImageElement>(null)
  const upScaleImage = useRef<HTMLImageElement>(null)
  const [compareLineLeft, setCompareLineLeft] = useState(0)
  const [mousePos, setMousePos] = useState({ x: 0, y: 0 })
  const [mouseInCanvas, setMouseInCanvas] = useState(false)
  const [mouseIsDrawLine, setMouseIsDrawLine] = useState(false)
  function draw() {
    const ctx = canvasRef.current?.getContext('2d')
    ctx.imageSmoothingEnabled = props.previewMode !== 'pixelated'
    const canvasWidth = canvasRef.current?.width
    const canvasHeight = canvasRef.current?.height
    if (!ctx) return
    ctx.clearRect(0, 0, canvasWidth, canvasHeight)
    ctx.drawImage(
      originImage.current,
      0,
      0,
      compareLineLeft / outImageScale / canvasScale,
      height / outImageScale,
      0,
      0,
      compareLineLeft,
      canvasHeight
    )
    ctx.drawImage(
      upScaleImage.current,
      compareLineLeft / canvasScale,
      0,
      width,
      height,
      compareLineLeft,
      0,
      canvasWidth,
      canvasHeight
    )
    let lineWidth = canvasWidth / 250
    let drawColor = '#ffffffab'
    if (isMouseInnerLine || mouseIsDrawLine) {
      lineWidth = canvasWidth / 200
      drawColor = '#fff'
    }
    ctx.fillStyle = drawColor
    // 绘制对比线
    {
      const defaultBoxSize = isMobile() ? canvasWidth / 13 : canvasWidth / 25
      const centerBoxSize = Math.min(
        Math.max(defaultBoxSize, 10),
        canvasWidth / 3
      )
      ctx.strokeStyle = drawColor
      ctx.lineWidth = lineWidth
      ctx.fillRect(
        compareLineLeft - lineWidth / 2,
        0,
        lineWidth,
        (canvasHeight - centerBoxSize) / 2
      )
      ctx.fillRect(
        compareLineLeft - lineWidth / 2,
        (canvasHeight + centerBoxSize) / 2,
        lineWidth,
        canvasHeight
      )
      ctx.beginPath()
      ctx.arc(
        compareLineLeft,
        canvasHeight / 2,
        centerBoxSize / 2,
        0,
        Math.PI * 2
      )
      ctx.fillStyle = '#0000006b'
      ctx.fill()
      ctx.stroke()
      ctx.closePath()
      ctx.fillStyle = drawColor
      ctx.strokeStyle = drawColor
      ctx.beginPath()
      ctx.moveTo(
        compareLineLeft + centerBoxSize / 5,
        canvasHeight / 2 - centerBoxSize / 5
      )
      ctx.lineTo(
        compareLineLeft + centerBoxSize / 5,
        canvasHeight / 2 + centerBoxSize / 5
      )
      ctx.lineTo(compareLineLeft + centerBoxSize / 3, canvasHeight / 2)

      ctx.fill()
      ctx.moveTo(
        compareLineLeft - centerBoxSize / 5,
        canvasHeight / 2 - centerBoxSize / 5
      )
      ctx.lineTo(
        compareLineLeft - centerBoxSize / 5,
        canvasHeight / 2 + centerBoxSize / 5
      )
      ctx.lineTo(compareLineLeft - centerBoxSize / 3, canvasHeight / 2)
      ctx.fill()
    }
  }
  const isMouseInnerLine =
    mouseInCanvas &&
    mousePos.x > compareLineLeft - canvasRef.current.width / 100 &&
    mousePos.x < compareLineLeft + canvasRef.current.width / 100
  useEffect(() => {
    originImage.current = new Image()
    originImage.current.src = orgingUrl
    upScaleImage.current = new Image()
    upScaleImage.current.src = upScaleUrl
  }, [orgingUrl, upScaleUrl])
  useEffect(() => {
    canvasRef.current.width = width * canvasScale
    canvasRef.current.height = height * canvasScale
    setCompareLineLeft((width * canvasScale) / 2)
  }, [width, height])
  useEffect(() => {
    draw()
  }, [compareLineLeft, isMouseInnerLine, props.previewMode])

  // if (isMouseInnerLine) {
  //   console.log('mouse in line')
  // }
  return (
    <div className={styles['image-compare-component']}>
      <canvas
        onMouseMove={(e) => {
          setMousePos(transformToCanvasPos(canvasRef.current!, e))
          if (!mouseIsDrawLine) return
          setCompareLineLeft(() => {
            const left = mousePos.x
            if (left < 0) return 0
            if (left > canvasRef.current.width) return canvasRef.current.width
            return left
          })
        }}
        onTouchMove={(e) => {
          setMousePos(
            transformToCanvasPos(canvasRef.current!, {
              clientX: e.touches[0].clientX,
              clientY: e.touches[0].clientY,
            })
          )
          if (!mouseIsDrawLine) return
          setCompareLineLeft(() => {
            const left = mousePos.x
            if (left < 0) return 0
            if (left > canvasRef.current.width) return canvasRef.current.width
            return left
          })
        }}
        onMouseEnter={() => {
          setMouseInCanvas(true)
        }}
        onMouseLeave={() => {
          if (!mouseIsDrawLine) {
            setMouseInCanvas(false)
            return
          }
          //   setMouseIsDrawLine(false)
          const dir = calculationMouseOutDir(
            mousePos,
            canvasRef.current.width,
            canvasRef.current.height
          )
          if (dir != 'left' && dir != 'right') return
          //  (这是为了防止鼠标在边缘时，鼠标移动过快，导致划线过快，导致划线位置错误)
          if (canvasRef.current.width - compareLineLeft < compareLineLeft) {
            //离右边近
            setCompareLineLeft(canvasRef.current.width - 1)
          } else {
            setCompareLineLeft(1)
          }
        }}
        onMouseDown={() => {
          if (!isMouseInnerLine) return
          setMouseIsDrawLine(true)
          window.addEventListener('mouseup', () => setMouseIsDrawLine(false), {
            once: true,
          })
        }}
        onTouchStart={() => {
          setMouseIsDrawLine(true)
          window.addEventListener('touchend', () => setMouseIsDrawLine(false), {
            once: true,
          })
        }}
        className={styles['orging-canvas']}
        style={{
          //   aspectRatio: width / height,
          cursor: isMouseInnerLine || mouseIsDrawLine ? 'ew-resize' : 'auto',
        }}
        ref={canvasRef}></canvas>
    </div>
  )
}
export default ImageCompare
